#define OS_Init_ProcSpec()      // Empty macro for MCC18


/**************************************************************************************************
 * 
 *  R E T U R N   F U N C T I O N S   F O R   M C C 1 8
 *
 **************************************************************************************************/


void _OS_ClrReadySetClrCanContinue (void);

/************************************************************************/
/* Save return address and return to scheduler                          */
/************************************************************************/

void OS_SchedRetPoint (void)
{
    _OS_SET_FSR_CUR_TASK_W(OS_CODE_POINTER_SIZE + 1);
    _postdec = _fsr1l - _OS_tempH;

    _OS_SavePC();
    _OS_bTaskReady = 1;
    
    _PIC18_POP();
}

/************************************************************************/
/* Return to scheduler without saving context                           */
/************************************************************************/
void OS_SchedRetPointNoSave (void)
{
    _PIC18_POP();
}

/************************************************************************/
/*                                                                      */
/************************************************************************/


void OS_ClearReady (void)
{
    _OS_temp = 0;
    _asm    goto    _OS_ClrReadySetClrCanContinue   _endasm
}

/************************************************************************/
/*                                                                      */
/************************************************************************/
void OS_ClearReadySetCanContinue (void)
{
    _OS_temp = 0xFF;
    _asm    goto    _OS_ClrReadySetClrCanContinue   _endasm
}


//------------------------------------------------------------------------------
// Additional function for reduce code.
// Called by "goto" from:
//      OS_ClearReady()
//      OS_ClearReadySetCanContinue()
// Stack contains address of task who called theese services
//------------------------------------------------------------------------------
void _OS_ClrReadySetClrCanContinue (void)
{


    OS_Flags.bEventError = 0;
    //_fsr = (_FSR_TYPE)&_OS_CurTask->cTempFSR1;
    
    _OS_SET_FSR_CUR_TASK_W(OS_CODE_POINTER_SIZE + 1);
    _postdec = _fsr1l - _OS_tempH;
    _OS_SavePC();
    _OS_bTaskReady = 0;

    #if defined(OS_ENABLE_TTIMERS)
        _OS_bTaskCanContinue = 0;
        if (_OS_temp & 0x01) _OS_bTaskCanContinue = 1;
    #endif

}
















/**************************************************************************************************
 * 
 * S E T   F S R   T O   P O I N T   O S _ C U R _ T A S K
 *
 * (for reduce used ROM)
 *
 **************************************************************************************************/

void _OS_SET_FSR_CUR_TASK (void)
{
    _asm    
        movlw   0
        goto __OS_SET_FSR_CUR_TASK_W
    _endasm
}



void __OS_SET_FSR_CUR_TASK_W (void)
{
    _asm
        addwf   _OS_CurTask + 0, 0, 0
        movwf   _fsr + 0, 0
        #if OS_BANK_TASKS == 0 
            clrf    _fsr + 1, 0
        #else
            movlw   0
            addwfc  _OS_CurTask + 1, 0, 0
            movwf   _fsr + 1, 0
        #endif
    _endasm
}




















/****************************************************************************************************
 * 
 * D I S A B L E   I N T E R R U P T S   W I T H    S A V I N G   G I E H : G I E L  
 * 
 * char OS_DI (void)   
 *
 ****************************************************************************************************/
/****************************************************************************************************
 * 
 * R E S T O R E   S A V E D   I N    O S _ D I ( )   I N T E R R U P T S
 * 
 * void OS_RI (char)   
 *
 ****************************************************************************************************/
//------------------------------------------------------------------------------
#define OS_DI_DEFINED
//------------------------------------------------------------------------------
char OS_DI (void)
{
    _asm
        movf    _intcon, 0, 0
        andlw   0xC0
    _DIH_REPEAT:
        bcf     _intcon, 7, 0
        btfsc   _intcon, 7, 0
        bra     _DIH_REPEAT
        btfss   _rcon, 7, 0
        bra     _DI_EXIT
    _DIL_REPEAT:
        bcf     _intcon, 6, 0
        btfsc   _intcon, 6, 0
        bra     _DIL_REPEAT
    _DI_EXIT:
    _endasm
}


void _OS_RI ()
{
    _asm
        btfsc   _wreg, 7, 0
        bsf     _intcon, 7, 0
        btfsc   _rcon, 7, 0
        btfss   _wreg, 6, 0
        bra     _RI_EXIT
        bsf     _intcon, 6, 0
    _RI_EXIT:
    _endasm

}








 
    
    
/****************************************************************************************************
 * 
 * C R I T I C A L   S E C T I O N S   W O R K 
 *
 ****************************************************************************************************/
//------------------------------------------------------------------------------
#ifdef OS_ENABLE_CRITICAL_SECTION
//------------------------------------------------------------------------------
    
/************************************************************************/
/* Enter critical section                                               */
/************************************************************************/
//------------------------------------------------------------------------------
#define OS_EnterCriticalSection_DEFINED
//------------------------------------------------------------------------------
void OS_EnterCriticalSection (void)
{
    _OST_INT_TYPE temp;
    temp = OS_DI();
    OS_Flags.bInCriticalSection = 1; 

    OS_Flags.bGIE_CTemp = 0;
    if (temp & 0x80) OS_Flags.bGIE_CTemp = 1;

    OS_Flags.bGIEL_CTemp = 0;
    if (temp & 0x40) OS_Flags.bGIEL_CTemp = 1;
}

/************************************************************************/
/* Leave critical section                                               */
/************************************************************************/
//------------------------------------------------------------------------------
#define OS_LeaveCriticalSection_DEFINED
//------------------------------------------------------------------------------
void OS_LeaveCriticalSection (void)
{
    char temp;
    OS_Flags.bInCriticalSection = 0; 
    temp = 0;
    if (OS_Flags.bGIE_CTemp) temp |= 0x80;
    if (OS_Flags.bGIEL_CTemp) temp |= 0x40;
    OS_RI(temp);
}

//------------------------------------------------------------------------------
#endif      //     #ifdef OS_ENABLE_CRITICAL_SECTION
//------------------------------------------------------------------------------


















//------------------------------------------------------------------------------
#ifdef OS_ENABLE_TTIMERS

/****************************************************************************************************
 * 
 *  D E L A Y S   W O R K 
 *
 ****************************************************************************************************/
/************************************************************************/
/*                                                                      */
/* Init task timer for counting                                         */
/* (internal system function)                                           */
/*                                                                      */
/************************************************************************/
//------------------------------------------------------------------------------
#define _OS_InitDelay_DEFINED
//------------------------------------------------------------------------------
void _OS_InitDelay (_OST_TTIMER Delay)
{

    char temp;
    temp = 0;               // This variable used to prevent FSR changing 
    if (Delay) temp = 1;    // when checking Delay after FSR set to task->Timer 
                            // See "if (temp & 1)" below
    
    _OS_SET_FSR_CUR_TASK();
    _OS_bTaskCanContinue = 0;
    _OS_bTaskDelay = 0;     // Clear bDelay to prevent timer changing in interrupt

    if (temp & 1)           
    {

        Delay ^= -1;
        Delay ++;
        
        _OS_CurTask->Timer = Delay;
        _OS_SET_FSR_CUR_TASK();
        _OS_bTaskDelay = 1;
        _OS_bTaskReady = 1;

    }
}

//______________________________________________________________________________
//******************************************************************************

#endif  // #ifdef OS_TIMER



    










    
    
    
    
    

    




















    
    
    
    
    

/****************************************************************************************************
 * 
 * 
 *  T A S K   W O R K   F U N C T I O N S
 *  
 *
 ****************************************************************************************************/


/************************************************************************/
/*                                                                      */
/* Create task in any free descriptor                                   */
/* On return:                                                           */
/*      =1 - OK,                                                        */
/*      =0 - there is no free descriptor                                */
/*                                                                      */
/************************************************************************/

//______________________________________________________________________________
////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
#define _OS_CreateTask_DEFINED
//------------------------------------------------------------------------------
bit _OS_CreateTask(_OST_INT_TYPE priority, OST_CODE_POINTER TaskAddr)
{
    OST_TASK_POINTER Task;
    
    OS_Flags.bError = 0;

    #if defined(OS_DISABLE_PRIORITY)
    priority = 0;
    #endif

    Task = (OST_TASK_POINTER)OS_TaskVars;
    _OS_temp = OS_TASKS;
    do {
        if (!Task->State.bEnable)
        {
            ((OST_TASK_STATE*)&priority)->bEnable = 1;
            ((OST_TASK_STATE*)&priority)->bReady = 1;
            

            Task->pTaskPointer = TaskAddr;
            #ifdef OS_ENABLE_TTIMERS
                Task->Timer = 0;
            #endif
            Task->cTempFSR1 = 0;
            *((OS_TASKS_BANK char*)&Task->State) = priority;
            _fsr = (_FSR_TYPE)Task;
            // Now fsr points to task descriptor
            OS_Flags.bError = 0;
            return 1;
        
        }
        Task ++;
    } while (_OS_temp--);
    
    // No free descriptor
    OS_Flags.bError = 1;
    return 0;
}




































/******************************************************************************************
 *
 *  D T I M E R S   W O R K  
 *
 ******************************************************************************************/
#ifdef OS_ENABLE_DTIMERS

/************************************************************************/
/*                                                                      */
/************************************************************************/
//------------------------------------------------------------------------------
#define _OS_CreateDTimer_DEFINED
//------------------------------------------------------------------------------
void _OS_CreateDTimer (OST_DTIMER *dtimer)
{
    _OS_temp = OS_DI();
    _fsr = (_FSR_TYPE) dtimer;

    _postinc = *((OS_BANK char*)&_OS_DTimers.Flags);
    // Here: bActive is set,
    //       bTimeout is cleared,
    //       bRun is cleared
    //       bNextEnable is copied

    _postinc = *((OS_BANK char*)&_OS_DTimers.Next + 0);
    _postinc = *((OS_BANK char*)&_OS_DTimers.Next + 1);
    _postinc = 0;
    #if  OS_DTIMER_SIZE >= 2
    _postinc = 0;
    #endif
    #if  OS_DTIMER_SIZE == 4
    _postinc = 0;
    _postinc = 0;
    #endif

    _OS_DTimers.Next = (OST_DTIMER*)dtimer;
    _OS_DTimers.Flags.bNextEnable = 1;
    
    OS_RI(_OS_temp);
}





/************************************************************************/
/*                                                                      */
/************************************************************************/
//------------------------------------------------------------------------------
#define _OS_DeleteDTimer_DEFINED
//------------------------------------------------------------------------------
void _OS_DeleteDTimer (OST_DTIMER *dtimer)
{

    OST_DTIMER *ptcb;
    char flags;
    _fsr = (_FSR_TYPE)dtimer;
    _OS_ClearIndfTimerActive;
    flags = _postinc;
    *((char*)&ptcb + 0) = _postinc;
    *((char*)&ptcb + 1) = _postinc;
    _fsr = (_FSR_TYPE)&_OS_DTimers;
REPEAT:
    if (_OS_CheckPostincTimerNextEnable)
    {
        if (_indf == *((char*)&dtimer + 0))
        {
            if (_preinc == *((char*)&dtimer + 1)){
                _OS_temp = OS_DI();
                _postdec = *((char*)&ptcb + 1);
                _postdec = *((char*)&ptcb + 0);
                
                
                if (!(flags & 0x8)) _OS_ClearIndfTimerNextEnable;   // Check for bNextEnable
                // If we check in other way (for example: !((OST_DTIMER_FLAGS*)&flags)->bNextEnable)
                // then compiler can use FSR0, as a result current pointer to dtimer will be lost
                return;
            }
            _fsr--;
        } 
        _asm
            movf    _postinc, 0, 0
            movff   _indf, _fsr + 1
            movwf   _fsr + 0, 0
        _endasm
        goto REPEAT;
    }
        
}



#endif  //  OS_ENABLE_DTIMERS


























/****************************************************************************************************
 * 
 * C H E C K   E V E N T   A N D   S E T / C L E A R   R E A D Y   F L A G 
 *
 * (internal system function) 
 *
 ****************************************************************************************************/


//------------------------------------------------------------------------------
#define _OS_CheckEvent_DEFINED
//------------------------------------------------------------------------------

#define bEvent  _OS_temp
void _OS_CheckEvent (void)
{
    OS_Flags.bTimeout = 0;
    _OS_SET_FSR_CUR_TASK();
    if (bEvent) {
        if (_OS_bTaskReady) {
            #ifdef OS_ENABLE_TTIMERS
                _OS_bTaskDelay = 0;
            #endif
            return;
        }
        _OS_bTaskReady = 1;
    } else {
        _OS_bTaskReady = 0;
    }
    #ifdef OS_ENABLE_TTIMERS
        if (_OS_bTaskTimeout && _OS_bTaskCanContinue) {
            OS_Flags.bTimeout = 1;
            return;
        }
    #endif
    _PIC18_POP();
}


    

        

        

